#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>

#include "common.h"

static const unsigned short defaultCenterProxyServerPort = 9417;
static const unsigned short defaultBroadcastServerPort = 7889;
static const unsigned short defaultDeviceManagerServerPort = 7890;

//static const TypeC256 defaultDeviceManagerServerIp = "zstengo.xicp.net:7890";
static const TypeC256 defaultDeviceManagerServerIp = "www.incastyun.cn:7890";

typedef struct _serverConnectInfo
{
		unsigned int ip;
		unsigned short port;
		unsigned char protoMainType;
		unsigned char protoSlaveType;
		unsigned char serverType;				//0 center server, 1 broadcast server 
}ServerConnectInfo;
static ServerConnectInfo centerServerInfo = {0, defaultCenterProxyServerPort, 0x00, 0x00, 0};
static ServerConnectInfo broadcastServerInfo = {0, defaultBroadcastServerPort, 0x0C, 0x00, 1};
static ServerConnectInfo deviceManagerServerInfo = {0, defaultDeviceManagerServerPort, 0x00, 0x00, 2};

static void* ThreadWork_ToCenterServer(void* arg);
static void* ThreadWork_ToBroadcastServer(void* arg);
static void* ThreadWork_TodeviceManagerServer(void* arg);
static void dealLogic(ServerConnectInfo* server);

extern SystemParam *pgSystemParam;

int initHeartbeat()
{
		//printf("into initHeartbeat\n");
		if(pgSystemParam == NULL)
		{
				printf("pgSystemParam == NULL ! {%s,%d}\n", __FILE__,__LINE__);	
				return -1;
		}
		
		pthread_t ptID;	
		if( pthread_create(&ptID, NULL, ThreadWork_ToCenterServer, (void *)&centerServerInfo) != 0 )
		{
				printf("Make thread failure {%s(%d)}\n",__FILE__,__LINE__);		
				return -2;
		}           	
	
		if( pthread_create(&ptID, NULL, ThreadWork_ToBroadcastServer, (void *)&broadcastServerInfo) != 0 )
		{
				printf("Make thread failure {%s(%d)}\n",__FILE__,__LINE__);		
				return -3;
		}
		
		if( pthread_create(&ptID, NULL, ThreadWork_TodeviceManagerServer, (void *)&deviceManagerServerInfo) != 0 )
		{
				printf("Make thread failure {%s(%d)}\n",__FILE__,__LINE__);		
				return -3;
		}
	
		return 0;
}


static void* ThreadWork_ToCenterServer(void* arg)
{
		ServerConnectInfo *centerServerInfo = (ServerConnectInfo*)arg;
		dealLogic(centerServerInfo);		
		
		return NULL;
}

static void* ThreadWork_ToBroadcastServer(void* arg)
{
		ServerConnectInfo *broadcastServerInfo = (ServerConnectInfo*)arg;
		dealLogic(broadcastServerInfo);		
		
		return NULL;
}

static void* ThreadWork_TodeviceManagerServer(void* arg)
{
		ServerConnectInfo *deviceManagerServerInfo = (ServerConnectInfo*)arg;
		dealLogic(deviceManagerServerInfo);		
		
		return NULL;
}

static void dealLogic(ServerConnectInfo* server)
{
		struct sockaddr_in  aimServerAddr;
		aimServerAddr.sin_family = AF_INET;
		
		struct timespec ts;
		struct timeval  tv;	
		static sem_t sem_tmp;
		static int ret;
		
		static unsigned char sendBuf[256];
		static unsigned short dataLen;
		static int headLen = 0;
		
		int privateDataInt = 0;
		int packageSize;
		
		static TypeC256 deviceManagerServerIp;
		memcpy(deviceManagerServerIp, defaultDeviceManagerServerIp, sizeof(TypeC256));
		
		switch(server->serverType)
		{
				case 0:
					dataLen = 4;
					break;
				case 1:
					dataLen = 4;
					break;
				case 2:
					dataLen = 4;			
					break;
				default:
					dataLen = 4;
					printf("server->serverType error ! server->serverType = %d\n", server->serverType);
					break;					
		}
		
		if( sem_init(&(sem_tmp), 1, 0) != 0   ) 
		{
				printf("sem_init failure {%s(%d)}\n",__FILE__,__LINE__);	
				return;
		}	
		
		unsigned int ipNum;
		unsigned short port;
		while(!IsExit())
		{
				gettimeofday(&tv, NULL); 
				
			  ts.tv_sec  = tv.tv_sec + 2;
		    ts.tv_nsec = tv.tv_usec * 1000;		
		    
		    sem_timedwait(&(sem_tmp),&ts);
		    
		    headLen = MakePackageHead(sendBuf, server->protoMainType, server->protoSlaveType, dataLen);
		
				if(server->serverType == 0)
		    {
		    		time_t now_t = time(NULL);
		    		ret = changeUIntToByte(now_t, sendBuf + headLen);
				    if(ret != 0)
				    {
				    		printf("sendBuf + 10 + idLen + passwdLen == NULL");	
				    		continue;
				    }
				    
				    port = server->port;
				    ret = creatIpNumAndPort(pgSystemParam->centerProxyServerIp, ipNum, port, &(pgSystemParam->centerProxyServerIpLock));
				    if(ret < 0)
				    {
				    		printf("creatIpNumAndPort fail ! ret = %d {%s,%d}\n", ret,__FILE__,__LINE__);
				    		continue;	
				    }
				    aimServerAddr.sin_addr.s_addr = ipNum;
				    aimServerAddr.sin_port = htons(port);
				    
				    //printf("center proxy server ip = %s\n", inet_ntoa(aimServerAddr.sin_addr));
		    }
		    else if(server->serverType == 1)
		    {
		    		ret = changeUIntToByte(privateDataInt, sendBuf + headLen);
				    if(ret != 0)
				    {
				    		printf("sendBuf + 10 + idLen + passwdLen == NULL");	
				    		continue;
				    }
				    privateDataInt ++;
				    		    
				    port = server->port;
				    ret = creatIpNumAndPort(pgSystemParam->broadcastServerIp, ipNum, port, &(pgSystemParam->broadcastServerIpLock));
				    if(ret < 0)
				    {
				    		//printf("creatIpNumAndPort fail ! ret = %d {%s,%d}\n", ret,__FILE__,__LINE__);
				    		continue;	
				    }
				    aimServerAddr.sin_addr.s_addr = ipNum;
				    aimServerAddr.sin_port = htons(port);
				    
				    //printf("broadcast server ip = %s, port = %d\n", inet_ntoa(aimServerAddr.sin_addr), port);
		    }
		    else
				{
		    		time_t now_t = time(NULL);
		    		ret = changeUIntToByte(now_t, sendBuf + headLen);
				    if(ret != 0)
				    {
				    		printf("sendBuf + 10 + idLen + passwdLen == NULL");	
				    		continue;
				    }
				    
				    //printf("prepare to change ! deviceManagerServerIp=%s,port=%d\n", deviceManagerServerIp,server->port);
				    port = server->port;
				    ret = creatIpNumAndPort(deviceManagerServerIp, ipNum, port, NULL);
				    if(ret < 0)
				    {
				    		printf("creatIpNumAndPort fail ! ret = %d {%s,%d}\n", ret,__FILE__,__LINE__);
				    		continue;	
				    }
				    aimServerAddr.sin_addr.s_addr = ipNum;
				    aimServerAddr.sin_port = htons(port);
				    
				    //printf("device manager server ip = %s\n", inet_ntoa(aimServerAddr.sin_addr));
		    }
				
				packageSize = headLen + dataLen;
				MainSend(sendBuf, packageSize, &aimServerAddr);
				
				//printf("headLen = %d, dataLen = %d\n", headLen,dataLen);
		}
}

